#include <concepts>
#include <stdexcept>

template <typename T>
  requires std::is_copy_constructible_v<T>
// requires std::is_copy_constructible<T>::value
// requires std::copyable<T>
T get_copy(T *value) {
  if (!value) {
    throw std::runtime_error("null pointer");
  }
  return *value;
}

struct NotCopyable {
  // --- Constructors ---
  NotCopyable() = default;
  NotCopyable(NotCopyable &&) = default;
  NotCopyable(const NotCopyable &) = delete;
  NotCopyable &operator=(NotCopyable &&) = default;
  NotCopyable &operator=(const NotCopyable &) = delete;
  ~NotCopyable() = default;

private:
};

int main(int argc, char **argv) {
  int x{42};
  int *p = &x;
  int y = get_copy(p);
  NotCopyable nc;
  auto nc_ptr = &nc;
  auto nc_copy = get_copy(nc_ptr); // error: 'NotCopyable' is not copyable

  return 0;
}
